
Alkaline.Runtime.Generator = function(){};

Alkaline.Runtime.Generator.prototype._init = function() {
	this._continuation = 0;
	this._yield_value = this.thisPropertyDoesNotExist;
	this._yield_exception = null;
	this._closing = false;
}

Alkaline.Runtime.Generator.prototype.next = function() {
	var nextValue = this._next(this);
	// if _continuation is less than 1 then the function returned without yielding anything (i.e. a return statement was encountered or the function finished executing)
	if (this._continuation < 0)
		throw StopIteration;
	return nextValue;
}

Alkaline.Runtime.Generator.prototype._yieldReturn = function() {
	var exception;
	if (exception = this._yield_exception) {
		this._yield_exception = null;
		throw exception;
	} else {
		var value = this._yield_value;
		// the unlikely name is used to obtain a reference to the primitive <undefined>
		this._yield_value = this.thisPropertyDoesNotExist;
		return value;
	}
}

Alkaline.Runtime.Generator.prototype['throw'] = function(exception) {
	this._yield_exception = exception;
	return this.next();
}

Alkaline.Runtime.Generator.prototype.send = function(yieldValue) {
	if (typeof yieldValue != 'undefined') {
		if (this._continuation == 0)
			throw new TypeError();
		this._yield_value = yieldValue;
	}
	return this.next();
}

Alkaline.Runtime.Generator.prototype.close = function() {
	this._closing = {};	// create a new object
	while (this._closing)
		try {
			this['throw'](this._closing);
		} catch(e) {
			if (e == this.closing || (e instanceof StopIteration))
				this._closing = false;
			else
				// a different error was thrown
				throw e;
		}
}

Alkaline.Runtime.Generator.prototype.toString = function() {
	return 'function (...) { [generator code] }';
}

Alkaline.Runtime.Generator.newInstance = function(argumentNames, generatorMethod) {
	var gen = function(argumentValues) {
		if (!(this instanceof gen))
			return new gen(arguments);
		this._init();
		for (var i = 0; i < argumentNames.length; i++)
			this['_local_' + argumentNames[i]] = argumentValues[i];
	};
	gen.prototype = new Alkaline.Runtime.Generator();
	gen.prototype._next = generatorMethod;
	return gen;
}
